﻿//-----------------------------------------------------------------------
// <copyright company="www.3WayWebdesign.de">
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
//
// <author>Michael Morbach</author>
// <email>Michael@3waywebdesign.de</email>
// <web>http://www.3waywebdesign.de</web>
//-----------------------------------------------------------------------

namespace Tww.IBAN.IBANUtilities.Model
{
    #region Imports

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Tww.IBAN.IBANUtilities.Converter;
    using Tww.IBAN.IBANUtilities.Validation;


    #endregion

    public class IBANModel
    {
        #region Ctors

        /// <summary>
        /// Initializes a new instance of the IBANModel class
        /// </summary>
        /// <param name="country">Country this IBAN belongs to</param>
        /// <param name="accountNumber">Accountnumber of this IBAN</param>
        public IBANModel( string country, string accountNumber )
        {
            if ( accountNumber.Any( f => !char.IsLetterOrDigit( f ) ) )
                throw new ArgumentException( string.Format( "Invalid argument for accountnumber {0}", accountNumber ) );

            this.Country = country.ToLower().Trim();
            this.AccountNumber = accountNumber.ToLower().Trim().TrimStart( '0' );
            this.Branch = string.Empty;
            this.BankCode = string.Empty;
            this.Miscellaneous = string.Empty;
        }

        /// <summary>
        /// Initializes a new instance of the IBANModel class
        /// </summary>
        /// <param name="country">Country this IBAN belongs to</param>
        /// <param name="accountNumber">Accountnumber of this IBAN</param>
        /// <param name="bankCode">Bankcode of this IBAN</param>
        public IBANModel( string country, string accountNumber, string bankCode )
            : this( country, accountNumber )
        {
            if ( bankCode.Any( f => !char.IsLetterOrDigit( f ) ) )
                throw new ArgumentException( string.Format( "Invalid argument for bankcode {0}", bankCode ) );

            this.BankCode = bankCode.ToLower().Trim().TrimStart( '0' );
        }

        /// <summary>
        /// Initializes a new instance of the IBANModel class
        /// </summary>
        /// <param name="country">Country this IBAN belongs to</param>
        /// <param name="accountNumber">Accountnumber of this IBAN</param>
        /// <param name="bankCode">Bankcode of this IBAN</param>
        /// <param name="branch">Branch of the bank for this IBAN</param>
        public IBANModel( string country, string accountNumber, string bankCode, string branch )
            : this( country, accountNumber, bankCode )
        {
            if ( branch.Any( f => !char.IsLetterOrDigit( f ) ) )
                throw new ArgumentException( string.Format( "Invalid argument for branch {0}", branch ) );

            this.Branch = branch.ToLower().Trim().TrimStart( '0' );
        }

        /// <summary>
        /// Initializes a new instance of the IBANModel class
        /// </summary>
        /// <param name="country">Country this IBAN belongs to</param>
        /// <param name="accountNumber">Accountnumber of this IBAN</param>
        /// <param name="bankCode">Bankcode of this IBAN</param>
        /// <param name="branch">Branch of the bank for this IBAN</param>
        /// <param name="misc">Other miscellaneous informations</param>
        public IBANModel( string country, string accountNumber, string bankCode, string branch, string misc )
            : this( country, accountNumber, bankCode, branch )
        {
            if ( misc.Any( f => !char.IsLetterOrDigit( f ) ) )
                throw new ArgumentException( string.Format( "Invalid argument for miscellaneous {0}", misc ) );

            this.Miscellaneous = misc.ToLower().Trim().TrimStart( '0' );
        }

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets the country this IBAN belongs to
        /// </summary>
        public string Country { get; private set; }

        /// <summary>
        /// Gets the bankcode of this IBAN
        /// </summary>
        public string BankCode { get; private set; }

        /// <summary>
        /// Gets the accountnumer of this IBAN
        /// </summary>
        public string AccountNumber { get; private set; }

        /// <summary>
        /// Gets the branch of the bank for this IBAN
        /// </summary>
        public string Branch { get; private set; }

        /// <summary>
        /// Gets the miscellaneous informations ( currently only relevant for island )
        /// </summary>
        public string Miscellaneous { get; private set; }

        #endregion

        #region Public Methods

        /// <summary>
        /// Gets the IBAN as a trimmed string like it is used in electronic form
        /// </summary>
        /// <param name="converter">Converter to convert this IBAN</param>
        /// <returns>IBAN as string ( e.g. -> DE21200500000123456000 )</returns>
        public string GetElectronicIBAN( IIBANConverter converter )
        {
            return converter.ConvertToElectronicIBAN( this );
        }

        /// <summary>
        /// Gets the IBAN as a four block string like it is used in paper form
        /// </summary>
        /// <param name="converter">Converter to convert this IBAN</param>
        /// <returns>IBAN as string ( e.g. -> IBAN DE21 2005 0000 0123 4560 00 )</returns>
        public string GetFourBlockIBAN( IIBANConverter converter )
        {
            return converter.ConvertToFourBlockIBAN( this );
        }

        /// <summary>
        /// Validates the IBANModel of correctness
        /// </summary>
        /// <param name="validator">Validator to validate this IBAN</param>
        /// <returns>True / False</returns>
        public bool ValidateData( IIBANValidator validator )
        {
            return validator.ValidateIBANModel( this );
        }

        /// <summary>
        /// Validates the IBANModel of correctness
        /// </summary>
        /// <returns>True / False</returns>
        public bool ValidateData()
        {
            return this.ValidateData( new DefaultIBANValidator() );
        }

        #endregion
    }
}
